/*
 * cm_storage_file.c
 *
 *  Created on: 2014年7月22日
 *      Author: chens
 */

#include <cm/file/cm_file.h>
#include <assert.h>
#include "cm_storage_def.h"

/*
 * @brief	初始化使用文件来存储数据的仓库
 */
void cmstorage_file_init(cm_storage **t)
{
	assert((*t)->type == CM_STORAGE_FILE);

	(*t)->storage = NULL;
	FILE *fp = fopen((*t)->url, "a+");
	if (fp == NULL) {
		cmstorage_close(t);
		return;
	}

	(*t)->storage = fp;
}

void cmstorage_file_close(cm_storage **t)
{
	if ((*t)->storage != NULL) {
		fclose((FILE*) (*t)->storage);
		(*t)->storage = NULL;
	}
}

/*
 * @brief	将数据放入文件中
 * @param	t：数据仓库的对象
 * 		head：数据的状态信息
 * 		data：所要放入的数据
 * @return	成功返回0 失败返回非0
 */
int cmstorage_file_put(const cm_storage *t, const struct cmstorage_head *head,
		const char *data)
{
	// TODO 写入失败，要恢复文件状态
	if (1 != fwrite(head, LEN_CM_STORAGE_HEAD, 1, (FILE *) t->storage))
		return -1;

	if (1 != fwrite(data, t->objsize, 1, (FILE *) t->storage))
		return -1;

	return 0;
}

/*
 * @brief	从文件中取出一条数据，文件指针保存在仓库对象中
 * @param	t：仓库对象
 * 		sort：取时的排序方式
 * 		state：所取数据需要满足的状态
 * 		data：用来存放数据的空间
 * 		size：data处空间的大小
 * @return	数据ID：在文件中的偏移，-1表示取失败
 */
int cmstorage_file_get(const cm_storage *t, enum CM_STORAGE_SORT sort,
		cm_satisfy cond, char *data, struct cmstorage_head* head)
{
	struct cmstorage_head temp;
	if (head == NULL)
		head = &temp;

	fseek((FILE*) t->storage, 0, SEEK_SET);
	int ret = -1;
	do {
		ret = fread(head, LEN_CM_STORAGE_HEAD, 1, (FILE *) t->storage);
		if (ret <= 0)
			break; /* error or EOF*/
		ret = fread(data, t->objsize, 1, (FILE*) t->storage);
		if (ret <= 0)
			break; /* error or EOF*/
		if (cond != NULL && cond(data)) {
			ret = ftell((FILE*) t->storage) - LEN_CM_STORAGE_HEAD
					- t->objsize;
			return ret;
		}
	} while (1);

	return -1;
}
